{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Batch size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What are batches\n",
    "\n",
    "Machine learning models are usually trained on batches of data. A batch is simply a number (usually the power of 2), that a model trains itself on in an iteration. For example, batch size 32 means that the model takes in these 32 entries of data, averaging its output, and trains on the 32 labels of the entires."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch size too small\n",
    "\n",
    "When batch sizes are too small, there are several issues that we may encounter."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Training takes a long time.\n",
    "\n",
    "When training on GPUs, data is sent to the GPU batch by batch, with the overhead of transfering data back and forth. If the batch size is too small, we spend a much higher percentage of time sending data than actually computing. This is the reason we usually prefer bigger batches."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The training does not converge.\n",
    "\n",
    "In probability theory, variance measures how much the input varies, how close on average are two inputs. Let's plot two distributions with different variances. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "from scipy import stats"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mu = 0\n",
    "variance = 1\n",
    "sigma = np.sqrt(variance)\n",
    "x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)\n",
    "plt.xlim(-10, 10)\n",
    "plt.ylim(0, 1)\n",
    "plt.plot(x, stats.norm.pdf(x, mu, sigma))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mu = 0\n",
    "variance = 10\n",
    "sigma = np.sqrt(variance)\n",
    "x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)\n",
    "plt.xlim(-10, 10)\n",
    "plt.ylim(0, 1)\n",
    "plt.plot(x, stats.norm.pdf(x, mu, sigma))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "See how the first distribution is narrower than the second distribution. That means, the number sampled (numbers yielded from) the distribution is closer to one another, and changes little. A smaller variance helps the machine learning model to learn faster, because it's easier to learn from a simpler input than from inputs that can change a lot. For that reason, averages are easier to learn than individuals."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Batch size too big"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Training takes a lot of time.\n",
    "\n",
    "When batch size is too big, trainig can also take a long time, but for different reasons. It's again related to variance.\n",
    "\n",
    "There are certain problems in machine learning that gradients can be small, close to 0. In such a case, when the batch is overly big, the gradients can average so close to zero that it hinders progress of convergence. Well, worry not! Most of us aren't rich enough to use those kind of batch sizes (because of expensive GPUs)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## So, how should I choose batch sizes?\n",
    "\n",
    "Batch sizes are very tricky. Both too big and too small can make training very slow. So make sure to try different batch sizes and observe before commiting to training the whole dataset."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Is it possible that the model only remembers the last batch it sees?\n",
    "\n",
    "Yes, in theory it's possible that the model only remembers the last batch it sees if the model isn't big enough or if you update too much. However, in practice, we iterate over the dataset over and over, and update the model little by little. It's very unlikely that the model only remembers the last batch it has seen."
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "767d51c1340bd893661ea55ea3124f6de3c7a262a8b4abca0554b478b1e2ff90"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
